package com.lninl.config;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

import javax.inject.Inject;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration

@PropertySource("classpath:config.properties")
public class SecurityConfiguration {
    @Inject
    Environment env;

    @Autowired
    private DataSource dataSource;

    @Bean
    CredentialsMatcher sha512Matcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName(env.getProperty("shiro.hashAlgorithmName"));
        credentialsMatcher.setHashIterations(env.getProperty("shiro.storedCredentialsHexEncoded", Integer.class));
        credentialsMatcher.setStoredCredentialsHexEncoded(env.getProperty("shiro.hashIterations", Boolean.class));
        return credentialsMatcher;
    }

    @Bean
    JdbcRealm myRealm() {
        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(dataSource);
        jdbcRealm.setPermissionsLookupEnabled(true);
        jdbcRealm.setSaltStyle(JdbcRealm.SaltStyle.COLUMN);
        jdbcRealm.setCredentialsMatcher(sha512Matcher());
        jdbcRealm.setAuthenticationQuery("select passphrase, CONCAT('${shiro.applicationSalt}', ':', salt) as salt from shiro_user where userid = ?");
        jdbcRealm.setUserRolesQuery("SELECT name FROM shiro_role LEFT JOIN shiro_user_role ON shiro_role.id = shiro_user_role.role_id LEFT JOIN shiro_user ON shiro_user_role.user_id = shiro_user.id WHERE userid = ?");
        jdbcRealm.setPermissionsQuery("SELECT permission FROM shiro_role_permission LEFT JOIN shiro_role ON shiro_role_permission.role_id = shiro_role.id WHERE shiro_role.name = ?");
        return jdbcRealm;
    }


    @Bean
    DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(shiroEhcacheManager());
        securityManager.setRealm(myRealm());
        return securityManager;
    }

    @Bean
    LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    EhCacheManager shiroEhcacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("ehcache-shiro.xml");
        return ehCacheManager;
    }


    @Bean
    ShiroFilterFactoryBean shiroFilter() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap());
        return shiroFilterFactoryBean;
    }

    private Map filterChainDefinitionMap() {
        Map filterChainDefinitionMap = new HashMap();
        filterChainDefinitionMap.put("/login","authc");
        filterChainDefinitionMap.put("/logout","logout");
        filterChainDefinitionMap.put("/account/**","user");
        return filterChainDefinitionMap;
    }
}
